/**
 * @file W25Q64.c
 * @author      JinChengLong (https://gitee.com/Datejin/)
 * @brief      FLASH读写函数
 * @version     0.1
 * @date        2023
 * 
 * @copyright   Copyright © 2025 by JinChengLong 
 * 
 * All rights reserved.
 * Unauthorized copying, reproduction, or redistribution of this file via any medium is strictly prohibited.  
 * Proprietary and confidential.
 *   
 */
#include "W25Q64.h"

#include "W25Q64_Ins.h"
#include "SPIa.h"





extern uint8_t C[],B[],D[],E[],B1[],D1[],E1[],F[],bizhi[],bi[],DHT[],DHT0[], ma[];



/**
 * @brief 初始化W25Q64
 * 
 */
void W25Q64_init(void)
{
	SPIa_init ();	
}

/**
 * @brief 读取ID
 * 
 * @param MID 返回厂商ID
 * @param DID 返回设备ID 
 */
void W25Q64_RID(uint8_t *MID,uint16_t *DID)//厂商ID和设备ID
{
	SPIa_start ();
	SPIa_getbyte(W25Q64_JEDEC_ID);//读ID号的指令
	*MID=SPIa_getbyte(0xFF);//随便给，得到厂商ID	
	*DID=SPIa_getbyte(0xFF);//随便给，得到设备ID高8位
	*DID <<= 8;
	*DID |=SPIa_getbyte(0xFF);//随便给，得到设备ID低8位
	SPIa_stop();
}

/**
 * @brief 写使能
 * 
 */
void W25Q64_enable(void )//发送写使能指令//写使能仅对之后的一条语句有用//写使能后自动关门
{
	SPIa_start ();
	SPIa_getbyte(W25Q64_WRITE_ENABLE);
	SPIa_stop();
}

/**
 * @brief 等待繁忙结束
 * 
 */
void W25Q64_waitbusy(void )//等待busy为零
{
	//uint16_t tim=100000;
	SPIa_start ();
	SPIa_getbyte(W25Q64_READ_STATUS_REGISTER_1);//指令码读状态寄存器一
	while(SPIa_getbyte(0xFF) &0x01==0x01)//随便给，接受数据,取出最低位,等待busy为0
	{
//		tim-=tim;
//		if(tim==0)
//		{
//			break;//超时不等
//		}
	}
	SPIa_stop();
}





//
/**
 * @brief 擦除扇形区域
 * 
 * @param add 第几个
 */
void W25Q64_clearerase(uint32_t add)
{
	
	W25Q64_enable();//注意：写入操作前必须写使能//不能由零变成一
	SPIa_start ();
	SPIa_getbyte(W25Q64_SECTOR_ERASE_4KB);
	SPIa_getbyte(add>>16);//三个字节的最高位字节0x12
	SPIa_getbyte(add>>8);	//0x34
	SPIa_getbyte(add);//0x56
	SPIa_stop();
	W25Q64_waitbusy();//事后等待
}



//////
/**
 * @brief 
 * 
 * @param add 		起始地址
 * @param dataarr 	接受的数组
 * @param count 	数据数量
 */
void W25Q64_readdata(uint32_t add, uint8_t  *dataarr,uint32_t count )//读取的页数可以非常大
{
	uint32_t i;
	SPIa_start ();
	SPIa_getbyte(W25Q64_READ_DATA);//发送指令
	

//交换发送三个字节的地址
	
	SPIa_getbyte(add>>16);//三个字节的最高位字节0x12
	SPIa_getbyte(add>>8);	//0x34
	SPIa_getbyte(add);//0x56

	for(i=0;i<count ;i++)
	{
		dataarr[i]=SPIa_getbyte(0xFF);//依次交换数据实现读取	
	}
	SPIa_stop();
}


//页编程写入数据的范围是0~256
/**
 * @brief 
 * 
 * @param add 		指定的起始地址
 * @param dataarr 	要写入的数组
 * @param count 	写入的数量
 */
void W25Q64_page(uint32_t add,uint8_t *dataarr,uint16_t count)//用指针传递数组
{
	W25Q64_enable();////注意：写入操作前必须写使能//不能由零变成一
	uint16_t i=0;
	SPIa_start ();
	SPIa_getbyte(W25Q64_PAGE_PROGRAM);//发送指令
	
//交换发送三个字节的地址

	SPIa_getbyte(add>>16);//三个字节的最高位字节0x12
	SPIa_getbyte(add>>8);	//0x34
	SPIa_getbyte(add);//0x56
	
		for(i=0;i<count ;i++)
		{
			SPIa_getbyte(dataarr[i]);//每个循环交换一次数据
		}
	
	
	SPIa_stop();
	W25Q64_waitbusy();//事后等待
}






/*2024.1.23	15:20 success
*Mr.Jin						*/




/**
 * @brief 任意写
 * 
 * @param add 指定的起始地址
 * @param count 写的大小
 * @param cc 	写的内容
 */
void neicun_write(uint32_t add,uint16_t count, uint8_t  cc[])
{
	int16_t i=0,j=0;
	uint8_t  dd[256];


	if(count %256 != 0)
	{
		count =(count /256+1)*256;
	}

	for (i=0;i<count  ;i++)
	{
		j=i/256;
		
		if(	i>=(0+j*256)  &  i<(256*(j+1))	)
		{
			dd[i-256*j]=cc[i];
			if(i==(256*(j+1)-1))
			{
				W25Q64_page(add+256*j,dd,256);
			}
		}
	}
}


/**
 * @brief 读初始化界面
 * 
 */
void W25_BACK(void)
{
	W25Q64_readdata(4096*100,B,1680);
	W25Q64_readdata(4096*101,D,1680);
	W25Q64_readdata(4096*102,E,1680);
	W25Q64_readdata(4096*103,B1,1680);
	W25Q64_readdata(4096*104,D1,1680);
	W25Q64_readdata(4096*105,E1,1680);
	W25Q64_readdata(4096*106,F,1680);

	W25Q64_readdata(4096*130,bizhi,1);
	W25Q64_readdata(4096*131,ma,4);
		
}










